home *** CD-ROM | disk | FTP | other *** search
/ SGI Freeware 1999 August / SGI Freeware 1999 August.iso / dist / fw_ghostscript.idb / usr / freeware / lib / ghostscript / 3.33 / ps2ascii.ps.z / ps2ascii.ps
Encoding:
Text File  |  1998-05-21  |  14.4 KB  |  482 lines

  1. %    Copyright (C) 1991, 1995 Aladdin Enterprises.  All rights reserved.
  2. % This file is part of GNU Ghostscript.
  3. % GNU Ghostscript is distributed in the hope that it will be useful, but
  4. % WITHOUT ANY WARRANTY.  No author or distributor accepts responsibility to
  5. % anyone for the consequences of using it or for whether it serves any
  6. % particular purpose or works at all, unless he says so in writing.  Refer
  7. % to the GNU Ghostscript General Public License for full details.
  8.  
  9. % Extract the ASCII text from a PostScript file.  Nothing is displayed.
  10. % Instead, ASCII information is written to stdout.  The idea is similar to
  11. % Glenn Reid's `distillery', only a lot more simple-minded, and less robust.
  12.  
  13. % If SIMPLE is defined, just the text is written, with a guess at line
  14. % breaks and word spacing.  If SIMPLE is not defined, lines are written
  15. % to stdout as follows:
  16. %
  17. %    C <r> <g> <b>
  18. %        Indicate the current color. (NOT IMPLEMENTED YET)
  19. %
  20. %    F <height> <width> (<fontname>)
  21. %        Indicate font height and width of a space.
  22. %
  23. %    P
  24. %        Indicate the end of the page.
  25. %    R <x> <y> <width> <height>
  26. %        Display a rectangle. (NOT IMPLEMENTED YET)
  27. %
  28. %    S <x> <y> (<string>) <width>
  29. %        Display a string.
  30. %
  31. % <r>, <g>, and <b> are RGB values expressed as integers between 0 and 1000.
  32. % <width> and <height> are integer dimensions in units of 1/720".
  33. % <x> and <y> are integer coordinates, in units of 1/720", with the origin
  34. %   at the lower left.
  35. % <string> and <fontname> are strings represented with the standard
  36. %   PostScript escape conventions.
  37. % Note that future versions of this program may add other output elements,
  38. %   so programs parsing the output should be prepared to ignore elements
  39. %   that they do not recognize.
  40.  
  41. % Note that this code will only work in all cases if systemdict is writable
  42. % and if `binding' the definitions of operators defined as procedures
  43. % is deferred.  For this reason, it is normally invoked with
  44. %    gs -q -dNODISPLAY -dNOBIND -dWRITESYSTEMDICT ps2ascii.ps
  45.  
  46. % Thanks to J Greely <jgreely@cis.ohio-state.edu> for improvements
  47. % to this code, and to Jerry Whelan <jerryw@abode.ccd.bnl.gov> for
  48. % motivating other improvements.
  49.  
  50. /QUIET true def
  51. systemdict wcheck { systemdict } { userdict } ifelse begin
  52. /.max where { pop } { /.max { 2 copy lt { exch } if pop } bind def } ifelse
  53. /SIMPLE dup where { pop true } { false } ifelse def
  54. /setglobal where
  55.  { pop currentglobal /setglobal load true setglobal }
  56.  { { } }
  57. ifelse
  58.  
  59. % Define a way to store and retrieve integers that survives save/restore.
  60. /.i.string0 (0               ) def
  61. /.i.string .i.string0 length string def
  62. /.iget { cvi } bind def
  63. /.iput { exch //.i.string exch copy cvs pop } bind def
  64. /.inew { //.i.string0 dup length string copy } bind def
  65.  
  66. % Disable the display operators.
  67.  
  68. /eofill { newpath } odef
  69. /erasepage { } odef
  70. /fill { newpath } odef
  71. /stroke { newpath } odef
  72.  
  73. % The image operators must read the input, but do nothing.
  74.  
  75. /colorimage where
  76.  { pop /colorimage { gsave nulldevice //colorimage grestore } odef
  77.  } if
  78. /image { gsave nulldevice //image grestore } odef
  79. /imagemask { gsave nulldevice //imagemask grestore } odef
  80.  
  81. % Redefine the end-of-page operators.
  82.  
  83. /copypage { SIMPLE { (\014) } { (P\n) } ifelse //print } odef
  84. /showpage { copypage erasepage initgraphics } odef
  85.  
  86. % Output the current color if necessary.
  87. /.color.r .inew def
  88.   .color.r -1 .iput        % make sure we write the color at the beginning
  89. /.color.g .inew def
  90. /.color.b .inew def
  91. /.showcolor
  92.  { SIMPLE not
  93.     { currentrgbcolor
  94.       1000 mul round cvi
  95.       3 1 roll 1000 mul round cvi
  96.       exch 1000 mul round cvi
  97.         % Stack: b g r
  98.       dup //.color.r .iget eq
  99.       2 index //.color.g .iget eq and
  100.       3 index //.color.b .iget eq and
  101.        { pop pop pop
  102.        }
  103.        { (C ) //print
  104.      dup //.color.r exch .iput .show==only
  105.          ( ) //print dup //.color.g exch .iput .show==only
  106.          ( ) //print dup //.color.b exch .iput .show==only
  107.      (\n) //print
  108.        }
  109.       ifelse
  110.     }
  111.    if
  112.  } bind def
  113. % Some programs that interpret the output of ps2ascii aren't prepared to
  114. % handle the C command, so ****** WE DISABLE IT ******.
  115. /.showcolor { } def
  116.  
  117. % Redefine `show'.
  118.  
  119. % Set things up so our output will be in tenths of a point, with origin at
  120. % lower left.  This isolates us from the peculiarities of individual devices.
  121.  
  122. /.show.ident.matrix matrix def
  123. /.show.ident
  124. % { //.show.ident.matrix defaultmatrix
  125. %        % Assume the original transformation is well-behaved.
  126. %   0.1 0 2 index dtransform abs exch abs .max /.show.scale exch def
  127. %   0.1 dup 3 -1 roll scale
  128.  { gsave initmatrix
  129.         % Assume the original transformation is well-behaved.
  130.    0.1 0 dtransform abs exch abs .max /.show.scale exch def
  131.    0.1 dup scale .show.ident.matrix currentmatrix
  132.    grestore
  133.  } bind def
  134. /.coord
  135.  { transform .show.ident itransform
  136.    exch round cvi exch round cvi
  137.  } odef
  138. /.dcoord
  139.  {        % Transforming distances is trickier, because
  140.         % the coordinate system might be rotated.
  141.    .show.ident pop
  142.    exch 0 dtransform
  143. %     dup 0 ne { dup mul exch dup mul add sqrt } { pop abs } ifelse
  144. dup mul exch dup mul add sqrt
  145.      .show.scale div round cvi
  146.    exch 0 exch dtransform
  147. %     exch dup 0 ne { dup mul exch dup mul add sqrt } { pop abs } ifelse
  148. dup mul exch dup mul add sqrt
  149.      .show.scale div round cvi
  150.  } odef
  151.  
  152. % Remember the current X, Y, and height.
  153. /.show.x .inew def
  154. /.show.y .inew def
  155. /.show.height .inew def
  156. % Remember the last character of the previous string; if it was a
  157. % hyphen preceded by a letter, we didn't output the hyphen.
  158. /.show.last (\000) def
  159. % Remember the current font.
  160. /.font.name 130 string def
  161. /.font.name.length .inew def
  162. /.font.height .inew def
  163. /.font.width .inew def
  164.  
  165. % We have to redirect stdout somehow....
  166. /.show.stdout { (%stdout) (w) file } bind def
  167.  
  168. % Make sure writing will work even if a program uses =string.
  169. /.show.string =string length string def
  170. /.show.=string =string length string def
  171. /.show==only
  172.  { //=string //.show.=string copy pop
  173.    dup type /stringtype eq
  174.     { dup length //.show.string length le
  175.        { dup rcheck { //.show.string copy } if
  176.        } if
  177.     } if
  178.    .show.stdout exch write==only
  179.    //.show.=string //=string copy pop
  180.  } odef
  181.  
  182. /.showfont    % <string> .showfont <string>
  183.  { gsave
  184.     % Try getting the height and width of the font from the FontBBox.
  185.      currentfont /FontBBox .knownget not { {0 0 0 0} } if
  186.      aload pop exch 4 -1 roll sub 3 1 roll exch sub
  187.      2 copy .max 0 ne
  188.       { currentfont /FontMatrix get dtransform
  189.       }
  190.       {    pop pop
  191.     % Fonts produced by dvips, among other applications, have
  192.     % BuildChar procedures that bomb out when given unexpected
  193.     % characters, and there is no way to determine whether a given
  194.     % character will do this.  So for Type 1 fonts, we measure a
  195.     % typical character ('X'); for others, we punt.
  196.     currentfont /FontType get 1 eq
  197.      { (X) stringwidth pop dup 1.3 mul
  198.      }
  199.      {    % No safe way to get the character size.  Punt.
  200.        0 0
  201.      }
  202.     ifelse
  203.       }
  204.      ifelse .dcoord exch
  205.      currentfont /FontName .knownget not { () } if
  206.      dup type /stringtype ne { //.show.string cvs } if
  207.    grestore
  208.     % Stack: height width fontname
  209.    SIMPLE
  210.     { pop pop //.show.height exch .iput }
  211.     { 2 index //.font.height .iget eq
  212.       2 index //.font.width .iget eq and
  213.       1 index //.font.name 0 //.font.name.length .iget getinterval eq and
  214.        { pop pop pop
  215.        }
  216.        { (F ) //print
  217.      3 -1 roll dup //.font.height exch .iput .show==only ( ) //print
  218.          exch dup //.font.width exch .iput .show==only ( ) //print
  219.      dup length //.font.name.length exch .iput
  220.          //.font.name cvs .show==only (\n) //print
  221.        }
  222.       ifelse
  223.     }
  224.    ifelse
  225.  } odef
  226.  
  227. % Define the letters -- characters which, if they occur followed by a hyphen
  228. % at the end of a line, cause the hyphen and line break to be ignored.
  229. /.letter.chars 100 dict def
  230. mark
  231.   65 1 90 { dup 32 add } for
  232. counttomark { StandardEncoding exch get .letter.chars exch dup put } repeat
  233. pop
  234.  
  235. % Define a set of characters which, if they occur at the start of a line,
  236. % are taken as indicating a paragraph break.
  237. /.break.chars 50 dict def
  238. mark
  239.   /bullet /dagger /daggerdbl /periodcentered /section
  240. counttomark { .break.chars exch dup put } repeat
  241. pop
  242.  
  243. % Define character translation to ASCII.
  244. % We have to do this for the entire character set.
  245. /.char.map 500 dict def
  246. /.chars.def { counttomark 2 idiv { .char.map 3 1 roll put } repeat pop } def
  247.     % Encode the printable ASCII characters.
  248. mark 32 1 126
  249.  { 1 string dup 0 4 -1 roll put
  250.    dup 0 get StandardEncoding exch get exch
  251.  }
  252. for .chars.def
  253.     % Encode accents.
  254. mark
  255.   /acute (') /caron (^) /cedilla (,) /circumflex (^)
  256.   /dieresis (") /grave (`) /ring (*) /tilde (~)
  257. .chars.def
  258.     % Encode the ISO accented characters.
  259. mark 192 1 255
  260.  { ISOLatin1Encoding exch get =string cvs
  261.    dup 0 1 getinterval 1 index dup length 1 sub 1 exch getinterval
  262.    .char.map 2 index known .char.map 2 index known and
  263.     { .char.map 3 -1 roll get .char.map 3 -1 roll get concatstrings
  264.       .char.map 3 1 roll put
  265.     }
  266.     { pop pop pop
  267.     }
  268.    ifelse
  269.  }
  270. for .chars.def
  271.     % Encode the remaining standard and ISO alphabetic characters.
  272. mark
  273.   /AE (AE) /Eth (DH) /OE (OE) /Thorn (Th)
  274.   /ae (ae) /eth (dh)
  275.   /ffi (ffi) /ffl (ffl) /fi (fi) /fl (fl)
  276.   /germandbls (ss) /oe (oe) /thorn (th)
  277. .chars.def
  278.     % Encode the other standard and ISO characters.
  279. mark
  280.   /brokenbar (|) /bullet (*) /copyright ((C)) /currency (#)
  281.   /dagger (#) /daggerdbl (##) /degree (o) /divide (/) /dotaccent (.)
  282.   /dotlessi (i)
  283.   /ellipsis (...) /emdash (--) /endash (-) /exclamdown (!)
  284.   /florin (f) /fraction (/)
  285.   /guillemotleft (<<) /guillemotright (>>)
  286.   /guilsingleft (<) /guilsingright (>) /hungarumlaut ("") /logicalnot (~)
  287.   /macron (_) /minus (-) /mu (u) /multiply (*)
  288.   /ogonek (,) /onehalf (1/2) /onequarter (1/4) /onesuperior (1)
  289.   /ordfeminine (-a) /ordmasculine (-o)
  290.   /paragraph (||) /periodcentered (*) /perthousand (o/oo) /plusminus (+-)
  291.   /questiondown (?) /quotedblbase (") /quotedblleft (") /quotedblright (")
  292.   /quotesinglbase (,) /quotesingle (') /registered ((R))
  293.   /section ($) /sterling (#)
  294.   /threequarters (3/4) /threesuperior (3) /trademark ((TM)) /twosuperior (2)
  295.   /yen (Y)
  296. .chars.def
  297.     % Encode a few common Symbol characters.
  298. mark
  299.   /asteriskmath (*) /copyrightsans ((C)) /copyrightserif ((C))
  300.   /greaterequal (>=) /lessequal (<=) /registersans ((R)) /registerserif ((R))
  301.   /trademarksans ((TM)) /trademarkserif ((TM))
  302. .chars.def
  303.  
  304. % Write out a string.  If it ends in a letter and a hyphen,
  305. % don't write the hyphen, and set .show.last to a hyphen;
  306. % otherwise, set .show.last to the character (or \000 if it was a hyphen).
  307. /.show.write    % <string>
  308.  { dup length 1 ge
  309.     { dup dup length 1 sub get
  310.       dup 45 eq        % hyphen
  311.        { 1 index length 1 gt
  312.           { 1 index dup length 2 sub get }
  313.       { //.show.last 0 get }
  314.      ifelse
  315.      currentfont /Encoding get exch get
  316.      //.letter.chars exch known
  317.       {    % Remove the hyphen
  318.         exch dup length 1 sub 0 exch getinterval exch
  319.       }
  320.       { pop 0
  321.       }
  322.      ifelse
  323.        }
  324.       if
  325.       //.show.last 0 3 -1 roll put
  326.     }
  327.    if
  328.     { dup currentfont /Encoding get exch get
  329.       dup //.char.map exch .knownget
  330.        { .show.stdout exch writestring pop pop
  331.        }
  332.        { currentfont /Encoding dup StandardEncoding eq
  333.      exch ISOLatin1Encoding eq or
  334.       {    % Untranslated character in standard encoding
  335.         pop .show.stdout exch write
  336.       }
  337.       {    % Character in non-standard encoding, substitute
  338.         pop pop .show.stdout (*) writestring
  339.       }
  340.      ifelse
  341.        }
  342.       ifelse
  343.     }
  344.    forall
  345.  } odef
  346. /.showstring1
  347.  { currentpoint .coord
  348.    3 -1 roll dup stringwidth 1 index 0 rmoveto
  349.    .dcoord pop
  350.     % Stack: x y string width
  351.    SIMPLE
  352.     { 2 index //.show.y .iget ne
  353.        {    % Try to figure out whether we have a line break
  354.         % or a paragraph break.
  355.      2 index //.show.y .iget sub abs
  356.      //.show.height .iget 1.3 mul ge
  357.      2 index length 0 gt
  358.       { 2 index 0 get currentfont /Encoding get exch get
  359.         //.break.chars exch known { pop true } if
  360.       }
  361.      if
  362.       { (\n\n)    % Paragraph
  363.       }
  364.       { ( )        % Line
  365.       }
  366.      ifelse //print
  367.      //.show.y 3 index .iput
  368.          //.show.x 4 index .iput
  369.        }
  370.        {    % If the word processor split a hyphenated word within
  371.         % the same line, put out the hyphen now.
  372.      //.show.last 0 get 45 eq { (-) //print } if
  373.        }
  374.       ifelse
  375.       3 index //.show.x .iget 10 add gt
  376.        { ( ) //print
  377.        }
  378.       if
  379.       4 1 roll .show.write pop add //.show.x exch .iput
  380.     }
  381.     { (S ) //print
  382.       4 -1 roll .show==only ( ) //print
  383.       3 -1 roll .show==only ( ) //print
  384.       exch .show==only ( ) //print
  385.       .show==only (\n) //print
  386.     }
  387.    ifelse
  388.  } odef
  389. /.showstring
  390.  { dup () eq { pop } { .showstring1 } ifelse
  391.  } bind def
  392.      
  393. % Redefine all the string display operators.
  394.  
  395. /show
  396.  { .showfont .showcolor .showstring
  397.  } odef
  398.  
  399. % We define all the other operators in terms of .show1.
  400. /.show1.string ( ) def
  401. /.show1 { //.show1.string exch 0 exch put //.show1.string .showstring } odef
  402. /ashow
  403.  { .showfont .showcolor
  404.    { .show1 2 copy rmoveto } forall
  405.    pop pop
  406.  } odef
  407. /awidthshow
  408.  { .showfont .showcolor
  409.     { dup .show1 4 index eq { 4 index 4 index rmoveto } if
  410.       2 copy rmoveto
  411.     }
  412.    forall
  413.    pop pop pop pop pop
  414.  } odef
  415. /widthshow
  416.  { .showfont .showcolor
  417.    //.show1.string 0 4 -1 roll put
  418.     { //.show1.string search not { exit } if
  419.       .showstring .showstring
  420.       2 index 2 index rmoveto
  421.     } loop
  422.    .showstring pop pop
  423.  } odef
  424. /kshow
  425.  { .showfont .showcolor
  426.     { .show1 dup exec } forall pop
  427.  } odef
  428. % We don't really do the right thing with the Level 2 show operators,
  429. % but we do something semi-reasonable.
  430. /xshow where
  431.  { pop /xshow { pop show } bind odef
  432.  } if
  433. /yshow where
  434.  { pop /yshow { pop show } bind odef
  435.  } if
  436. /xyshow where
  437.  { pop /xyshow { pop show } bind odef
  438.  } if
  439. /glyphshow where
  440.  { pop /glyphshow
  441.     { currentfont /Encoding .knownget not { {} } if
  442.       0 1 2 index length 1 sub
  443.        {    % Stack: glyph encoding index
  444.      2 copy get 3 index eq { exch pop exch pop null exit } if
  445.        }
  446.       for null eq { (X) dup 0 4 -1 roll put show } { pop } ifelse
  447.     } bind odef
  448.  } if
  449.  
  450. % Redirect the printing operators.
  451.  
  452. /.stdout (_temp_.out) (w) file def
  453. /.stderr (_temp_.err) (w) file def
  454. /print { //.stdout exch writestring } odef
  455. /=only { //.stdout exch write=only } odef
  456. /==only { //.stdout exch write==only } odef
  457.  
  458. end
  459.  
  460. % Bind the operators we just defined, and all the others if we didn't
  461. % do it before.  Also reenable 'bind' for future files.
  462.  
  463. .bindoperators
  464. NOBIND currentdict systemdict ne and
  465.  { systemdict begin .bindoperators end }
  466. if
  467. NOBIND
  468.  { /bind /.bind load def }
  469. if
  470.  
  471. % Make systemdict read-only if it wasn't already.
  472.  
  473. systemdict wcheck { systemdict readonly pop } if
  474.  
  475. % Restore the current local/global VM mode.
  476.  
  477. exec
  478.